package com.zenithmind.version.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.zenithmind.common.context.UserContext;
import com.zenithmind.version.mapper.CommitMapper;
import com.zenithmind.version.pojo.domain.Commit;
import com.zenithmind.version.pojo.dto.CommitCreateDTO;
import com.zenithmind.version.pojo.query.CommitQueryDTO;
import com.zenithmind.version.pojo.vo.CommitVO;
import com.zenithmind.version.service.CommitService;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * 提交服务实现类
 * 
 * @author ZenithMind Team
 * @since 2025-01-09
 */
@Slf4j
@Service
@RequiredArgsConstructor
public class CommitServiceImpl extends ServiceImpl<CommitMapper, Commit> implements CommitService {

    @Override
    @Transactional(rollbackFor = Exception.class)
    public CommitVO createCommit(CommitCreateDTO createDTO) {
        log.info("创建提交: {}", createDTO.getMessage());
        
        // 生成提交哈希
        String commitHash = generateCommitHash(createDTO.getRepositoryId(), createDTO.getMessage());
        
        Commit commit = new Commit();
        BeanUtils.copyProperties(createDTO, commit);
        commit.setHash(commitHash);
        commit.setShortHash(commitHash.substring(0, Math.min(8, commitHash.length())));
        commit.setAuthorId(UserContext.getUserId());
        commit.setCommitterId(UserContext.getUserId());
        commit.setCommitTime(LocalDateTime.now());
        commit.setCreateTime(LocalDateTime.now());
        commit.setUpdateTime(LocalDateTime.now());
        
        save(commit);
        
        return convertToVO(commit);
    }

    @Override
    public IPage<CommitVO> getCommitPage(CommitQueryDTO queryDTO) {
        log.info("分页查询提交");

        // 参数验证
        if (queryDTO.getCurrent() == null || queryDTO.getCurrent() < 1) {
            queryDTO.setCurrent(1);
        }
        if (queryDTO.getSize() == null || queryDTO.getSize() < 1) {
            queryDTO.setSize(10);
        }
        if (queryDTO.getSize() > 100) {
            queryDTO.setSize(100); // 限制最大页面大小
        }

        Page<Commit> page = new Page<>(queryDTO.getCurrent(), queryDTO.getSize());

        // 构建查询条件
        LambdaQueryWrapper<Commit> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(queryDTO.getRepositoryId() != null, Commit::getRepositoryId, queryDTO.getRepositoryId())
               .eq(queryDTO.getBranchName() != null && !queryDTO.getBranchName().trim().isEmpty(),
                   Commit::getBranchName, queryDTO.getBranchName())
               .eq(queryDTO.getAuthorId() != null, Commit::getAuthorId, queryDTO.getAuthorId())
               .and(queryDTO.getKeyword() != null && !queryDTO.getKeyword().trim().isEmpty(), w ->
                   w.like(Commit::getMessage, queryDTO.getKeyword().trim())
                    .or()
                    .like(Commit::getHash, queryDTO.getKeyword().trim())
               )
               .orderByDesc(Commit::getCommitTime);

        IPage<Commit> commitPage = page(page, wrapper);

        // 转换为VO
        Page<CommitVO> resultPage = new Page<>(commitPage.getCurrent(), commitPage.getSize(), commitPage.getTotal());
        List<CommitVO> records = new ArrayList<>();
        for (Commit commit : commitPage.getRecords()) {
            records.add(convertToVO(commit));
        }
        resultPage.setRecords(records);

        log.info("分页查询提交完成: 总数={}, 当前页={}", commitPage.getTotal(), records.size());
        return resultPage;
    }

    @Override
    public CommitVO getCommitDetail(String id) {
        log.info("获取提交详情: {}", id);
        
        Commit commit = getById(id);
        if (commit == null) {
            throw new RuntimeException("提交不存在");
        }
        
        return convertToVO(commit);
    }

    @Override
    public CommitVO getCommitByHash(String repositoryId, String commitHash) {
        log.info("根据哈希获取提交: repositoryId={}, commitHash={}", repositoryId, commitHash);

        // 参数验证
        if (repositoryId == null || repositoryId.trim().isEmpty()) {
            throw new IllegalArgumentException("仓库ID不能为空");
        }
        if (commitHash == null || commitHash.trim().isEmpty()) {
            throw new IllegalArgumentException("提交哈希不能为空");
        }

        // 查询提交
        LambdaQueryWrapper<Commit> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(Commit::getRepositoryId, repositoryId.trim())
               .eq(Commit::getHash, commitHash.trim());

        Commit commit = getOne(wrapper);

        if (commit != null) {
            log.info("找到提交: {}", commitHash);
            return convertToVO(commit);
        } else {
            log.info("未找到提交: {}", commitHash);
            return null;
        }
    }

    @Override
    public List<CommitVO> getRepositoryCommits(String repositoryId, String branchName, Integer limit) {
        log.info("获取仓库提交历史: repositoryId={}, branchName={}", repositoryId, branchName);

        if (repositoryId == null || repositoryId.trim().isEmpty()) {
            throw new IllegalArgumentException("仓库ID不能为空");
        }
        if (limit == null || limit <= 0) limit = 50;

        LambdaQueryWrapper<Commit> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(Commit::getRepositoryId, repositoryId.trim())
               .eq(branchName != null && !branchName.trim().isEmpty(), Commit::getBranchName, branchName)
               .orderByDesc(Commit::getCommitTime)
               .last("LIMIT " + limit);

        List<Commit> commits = list(wrapper);
        List<CommitVO> result = new ArrayList<>();
        for (Commit commit : commits) {
            result.add(convertToVO(commit));
        }

        log.info("获取到 {} 个提交", result.size());
        return result;
    }

    @Override
    public List<CommitVO> getBranchCommits(String repositoryId, String branchName, Integer limit) {
        log.info("获取分支提交历史: repositoryId={}, branchName={}", repositoryId, branchName);

        if (repositoryId == null || repositoryId.trim().isEmpty()) {
            throw new IllegalArgumentException("仓库ID不能为空");
        }
        if (branchName == null || branchName.trim().isEmpty()) {
            throw new IllegalArgumentException("分支名称不能为空");
        }
        if (limit == null || limit <= 0) limit = 50;

        LambdaQueryWrapper<Commit> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(Commit::getRepositoryId, repositoryId.trim())
               .eq(Commit::getBranchName, branchName.trim())
               .orderByDesc(Commit::getCommitTime)
               .last("LIMIT " + limit);

        List<Commit> commits = list(wrapper);
        List<CommitVO> result = new ArrayList<>();
        for (Commit commit : commits) {
            result.add(convertToVO(commit));
        }

        log.info("获取到分支 {} 的 {} 个提交", branchName, result.size());
        return result;
    }

    @Override
    public List<CommitVO> getUserCommits(String authorId, String repositoryId, Integer limit) {
        log.info("获取用户提交历史: authorId={}, repositoryId={}", authorId, repositoryId);

        if (authorId == null || authorId.trim().isEmpty()) {
            throw new IllegalArgumentException("作者ID不能为空");
        }
        if (limit == null || limit <= 0) limit = 50;

        LambdaQueryWrapper<Commit> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(Commit::getAuthorId, authorId.trim())
               .eq(repositoryId != null && !repositoryId.trim().isEmpty(), Commit::getRepositoryId, repositoryId)
               .orderByDesc(Commit::getCommitTime)
               .last("LIMIT " + limit);

        List<Commit> commits = list(wrapper);
        List<CommitVO> result = new ArrayList<>();
        for (Commit commit : commits) {
            result.add(convertToVO(commit));
        }

        log.info("获取到用户 {} 的 {} 个提交", authorId, result.size());
        return result;
    }

    @Override
    public List<Object> getCommitChanges(String commitId) {
        log.info("获取提交的文件变更: commitId={}", commitId);

        // 参数验证
        if (commitId == null || commitId.trim().isEmpty()) {
            throw new IllegalArgumentException("提交ID不能为空");
        }

        // 检查提交是否存在
        Commit commit = getById(commitId);
        if (commit == null) {
            throw new RuntimeException("提交不存在: " + commitId);
        }

        // 构建文件变更信息
        List<Object> changes = new ArrayList<>();

        // 这里应该查询实际的文件变更记录
        // 暂时返回模拟数据
        Map<String, Object> change1 = new HashMap<>();
        change1.put("fileName", "example.java");
        change1.put("changeType", "modified");
        change1.put("additions", 10);
        change1.put("deletions", 5);
        changes.add(change1);

        Map<String, Object> change2 = new HashMap<>();
        change2.put("fileName", "README.md");
        change2.put("changeType", "added");
        change2.put("additions", 20);
        change2.put("deletions", 0);
        changes.add(change2);

        log.info("获取到提交 {} 的 {} 个文件变更", commitId, changes.size());
        return changes;
    }

    @Override
    public List<CommitVO> getParentCommits(String commitId) {
        log.info("获取提交的父提交: commitId={}", commitId);

        // 参数验证
        if (commitId == null || commitId.trim().isEmpty()) {
            throw new IllegalArgumentException("提交ID不能为空");
        }

        // 检查提交是否存在
        Commit commit = getById(commitId);
        if (commit == null) {
            throw new RuntimeException("提交不存在: " + commitId);
        }

        // 这里应该查询父提交关系表，暂时返回空列表
        List<CommitVO> parents = new ArrayList<>();

        log.info("获取到提交 {} 的 {} 个父提交", commitId, parents.size());
        return parents;
    }

    @Override
    public List<CommitVO> getChildCommits(String commitId) {
        log.info("获取提交的子提交: commitId={}", commitId);

        // 参数验证
        if (commitId == null || commitId.trim().isEmpty()) {
            throw new IllegalArgumentException("提交ID不能为空");
        }

        // 检查提交是否存在
        Commit commit = getById(commitId);
        if (commit == null) {
            throw new RuntimeException("提交不存在: " + commitId);
        }

        // 这里应该查询子提交关系表，暂时返回空列表
        List<CommitVO> children = new ArrayList<>();

        log.info("获取到提交 {} 的 {} 个子提交", commitId, children.size());
        return children;
    }

    @Override
    public Object compareCommits(String repositoryId, String fromCommit, String toCommit) {
        log.info("比较两个提交的差异: repositoryId={}, fromCommit={}, toCommit={}", repositoryId, fromCommit, toCommit);

        // 参数验证
        if (repositoryId == null || repositoryId.trim().isEmpty()) {
            throw new IllegalArgumentException("仓库ID不能为空");
        }
        if (fromCommit == null || fromCommit.trim().isEmpty()) {
            throw new IllegalArgumentException("源提交不能为空");
        }
        if (toCommit == null || toCommit.trim().isEmpty()) {
            throw new IllegalArgumentException("目标提交不能为空");
        }

        // 构建比较结果
        Map<String, Object> comparison = new HashMap<>();
        comparison.put("repositoryId", repositoryId);
        comparison.put("fromCommit", fromCommit);
        comparison.put("toCommit", toCommit);
        comparison.put("changedFiles", new ArrayList<>());
        comparison.put("additions", 0);
        comparison.put("deletions", 0);
        comparison.put("compareTime", LocalDateTime.now());

        log.info("提交比较完成: {} -> {}", fromCommit, toCommit);
        return comparison;
    }

    @Override
    public List<CommitVO> getCommitsBetween(String repositoryId, String fromCommit, String toCommit) {
        log.info("获取两个提交之间的提交列表: repositoryId={}, fromCommit={}, toCommit={}", repositoryId, fromCommit, toCommit);

        // 参数验证
        if (repositoryId == null || repositoryId.trim().isEmpty()) {
            throw new IllegalArgumentException("仓库ID不能为空");
        }
        if (fromCommit == null || fromCommit.trim().isEmpty()) {
            throw new IllegalArgumentException("起始提交不能为空");
        }
        if (toCommit == null || toCommit.trim().isEmpty()) {
            throw new IllegalArgumentException("结束提交不能为空");
        }

        // 这里应该实现Git提交区间查询逻辑
        // 暂时返回空列表，实际应该根据Git历史查询两个提交之间的所有提交
        List<CommitVO> result = new ArrayList<>();

        log.info("提交区间查询完成: {} -> {}, 找到 {} 个提交", fromCommit, toCommit, result.size());
        return result;
    }

    @Override
    public List<CommitVO> searchCommits(String repositoryId, String keyword, String branchName, String authorId, Integer limit) {
        log.info("搜索提交: repositoryId={}, keyword={}, branchName={}, authorId={}", repositoryId, keyword, branchName, authorId);

        if (repositoryId == null || repositoryId.trim().isEmpty()) {
            throw new IllegalArgumentException("仓库ID不能为空");
        }
        if (keyword == null || keyword.trim().isEmpty()) {
            return new ArrayList<>();
        }
        if (limit == null || limit <= 0) limit = 20;

        LambdaQueryWrapper<Commit> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(Commit::getRepositoryId, repositoryId.trim())
               .eq(branchName != null && !branchName.trim().isEmpty(), Commit::getBranchName, branchName)
               .eq(authorId != null && !authorId.trim().isEmpty(), Commit::getAuthorId, authorId)
               .and(w -> w.like(Commit::getMessage, keyword.trim())
                          .or()
                          .like(Commit::getHash, keyword.trim()))
               .orderByDesc(Commit::getCommitTime)
               .last("LIMIT " + limit);

        List<Commit> commits = list(wrapper);
        List<CommitVO> result = new ArrayList<>();
        for (Commit commit : commits) {
            result.add(convertToVO(commit));
        }

        log.info("搜索到 {} 个提交", result.size());
        return result;
    }

    @Override
    public Object getCommitStatistics(String repositoryId, String branchName) {
        log.info("获取提交统计信息: repositoryId={}, branchName={}", repositoryId, branchName);

        // 参数验证
        if (repositoryId == null || repositoryId.trim().isEmpty()) {
            throw new IllegalArgumentException("仓库ID不能为空");
        }

        // 构建查询条件
        LambdaQueryWrapper<Commit> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(Commit::getRepositoryId, repositoryId.trim())
               .eq(branchName != null && !branchName.trim().isEmpty(), Commit::getBranchName, branchName);

        long totalCommits = count(wrapper);

        // 构建统计信息
        Map<String, Object> statistics = new HashMap<>();
        statistics.put("repositoryId", repositoryId);
        statistics.put("branchName", branchName);
        statistics.put("totalCommits", totalCommits);
        statistics.put("statisticsTime", LocalDateTime.now());

        log.info("提交统计信息获取完成: 总提交数={}", totalCommits);
        return statistics;
    }

    @Override
    public Object getUserCommitStatistics(String authorId, String repositoryId) {
        log.info("获取用户提交统计: authorId={}, repositoryId={}", authorId, repositoryId);

        // 参数验证
        if (authorId == null || authorId.trim().isEmpty()) {
            throw new IllegalArgumentException("作者ID不能为空");
        }

        // 构建查询条件
        LambdaQueryWrapper<Commit> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(Commit::getAuthorId, authorId.trim())
               .eq(repositoryId != null && !repositoryId.trim().isEmpty(), Commit::getRepositoryId, repositoryId);

        long userCommits = count(wrapper);

        // 构建统计信息
        Map<String, Object> statistics = new HashMap<>();
        statistics.put("authorId", authorId);
        statistics.put("repositoryId", repositoryId);
        statistics.put("totalCommits", userCommits);
        statistics.put("statisticsTime", LocalDateTime.now());

        log.info("用户提交统计信息获取完成: 用户提交数={}", userCommits);
        return statistics;
    }

    @Override
    public Object getCommitActivity(String repositoryId, String startDate, String endDate) {
        log.info("获取提交活动统计: repositoryId={}, startDate={}, endDate={}", repositoryId, startDate, endDate);

        // 参数验证
        if (repositoryId == null || repositoryId.trim().isEmpty()) {
            throw new IllegalArgumentException("仓库ID不能为空");
        }

        // 构建活动统计信息
        Map<String, Object> activity = new HashMap<>();
        activity.put("repositoryId", repositoryId);
        activity.put("startDate", startDate);
        activity.put("endDate", endDate);
        activity.put("dailyCommits", new ArrayList<>());
        activity.put("totalCommits", 0);
        activity.put("statisticsTime", LocalDateTime.now());

        log.info("提交活动统计信息获取完成");
        return activity;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public CommitVO revertCommit(String repositoryId, String commitId, String branchName, String userId) {
        log.info("回滚提交: repositoryId={}, commitId={}, branchName={}", repositoryId, commitId, branchName);

        // 参数验证
        if (repositoryId == null || repositoryId.trim().isEmpty()) {
            throw new IllegalArgumentException("仓库ID不能为空");
        }
        if (commitId == null || commitId.trim().isEmpty()) {
            throw new IllegalArgumentException("提交ID不能为空");
        }
        if (branchName == null || branchName.trim().isEmpty()) {
            throw new IllegalArgumentException("分支名称不能为空");
        }

        // 检查提交是否存在
        Commit commit = getById(commitId);
        if (commit == null) {
            throw new RuntimeException("提交不存在: " + commitId);
        }

        // 这里应该实现实际的Git回滚逻辑
        log.info("执行提交回滚: {} 在分支 {}", commitId, branchName);

        // 暂时返回原提交信息
        return convertToVO(commit);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public CommitVO cherryPickCommit(String repositoryId, String commitId, String targetBranch, String userId) {
        log.info("挑选提交: repositoryId={}, commitId={}, targetBranch={}", repositoryId, commitId, targetBranch);

        // 参数验证
        if (repositoryId == null || repositoryId.trim().isEmpty()) {
            throw new IllegalArgumentException("仓库ID不能为空");
        }
        if (commitId == null || commitId.trim().isEmpty()) {
            throw new IllegalArgumentException("提交ID不能为空");
        }
        if (targetBranch == null || targetBranch.trim().isEmpty()) {
            throw new IllegalArgumentException("目标分支不能为空");
        }

        // 检查提交是否存在
        Commit commit = getById(commitId);
        if (commit == null) {
            throw new RuntimeException("提交不存在: " + commitId);
        }

        // 这里应该实现实际的Git cherry-pick逻辑
        log.info("执行提交挑选: {} 到分支 {}", commitId, targetBranch);

        // 暂时返回原提交信息
        return convertToVO(commit);
    }

    @Override
    public Object getCommitGraph(String repositoryId, String branchName, Integer limit) {
        log.info("获取提交图谱: repositoryId={}, branchName={}", repositoryId, branchName);

        // 参数验证
        if (repositoryId == null || repositoryId.trim().isEmpty()) {
            throw new IllegalArgumentException("仓库ID不能为空");
        }
        if (limit == null || limit <= 0) limit = 100;

        // 构建提交图谱信息
        Map<String, Object> graph = new HashMap<>();
        graph.put("repositoryId", repositoryId);
        graph.put("branchName", branchName);
        graph.put("nodes", new ArrayList<>());
        graph.put("edges", new ArrayList<>());
        graph.put("limit", limit);

        log.info("提交图谱获取完成");
        return graph;
    }

    @Override
    public Boolean validateCommitHash(String repositoryId, String commitHash) {
        log.info("验证提交哈希: repositoryId={}, commitHash={}", repositoryId, commitHash);

        // 参数验证
        if (repositoryId == null || repositoryId.trim().isEmpty()) {
            throw new IllegalArgumentException("仓库ID不能为空");
        }
        if (commitHash == null || commitHash.trim().isEmpty()) {
            throw new IllegalArgumentException("提交哈希不能为空");
        }

        // 检查提交是否存在
        LambdaQueryWrapper<Commit> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(Commit::getRepositoryId, repositoryId.trim())
               .eq(Commit::getHash, commitHash.trim());

        boolean exists = count(wrapper) > 0;
        log.info("提交哈希验证结果: {}", exists ? "有效" : "无效");
        return exists;
    }

    @Override
    public Object getCommitSignature(String commitId) {
        log.info("获取提交签名信息: commitId={}", commitId);

        // 参数验证
        if (commitId == null || commitId.trim().isEmpty()) {
            throw new IllegalArgumentException("提交ID不能为空");
        }

        // 检查提交是否存在
        Commit commit = getById(commitId);
        if (commit == null) {
            throw new RuntimeException("提交不存在: " + commitId);
        }

        // 构建签名信息
        Map<String, Object> signature = new HashMap<>();
        signature.put("commitId", commitId);
        signature.put("signed", false);
        signature.put("signatureType", null);
        signature.put("keyId", null);
        signature.put("verificationStatus", "unsigned");

        log.info("提交签名信息获取完成");
        return signature;
    }

    /**
     * 生成提交哈希
     */
    private String generateCommitHash(String repositoryId, String message) {
        // 实现简单的哈希生成逻辑
        String input = repositoryId + "_" + message + "_" + System.currentTimeMillis();
        return "commit_" + Math.abs(input.hashCode());
    }

    /**
     * 转换为VO
     */
    private CommitVO convertToVO(Commit commit) {
        CommitVO vo = new CommitVO();
        BeanUtils.copyProperties(commit, vo);

        // 补充字段转换
        if (commit.getCreateTime() != null) {
            vo.setCreateTime(commit.getCreateTime());
        }
        // CommitVO没有updateTime字段，使用createTime代替
        if (commit.getCommitTime() != null) {
            vo.setCreateTime(commit.getCommitTime());
        }

        return vo;
    }
}
